from fastapi import HTTPException

from datetime import datetime


from src.database.models import (
    Forecast,
    Weather_condition,
    Region
)
from src.weather_service.schemas_forecast import (
    Upload_forecast,
    Update_forecast,
    Forecast_to_sql,
    Forecast_response
)

from src.database.my_crud import My_crud

from src.user_service.service.auth import raise_401_error

forecast_crud = My_crud(Forecast)
weather_condition_crud = My_crud(Weather_condition)
region_crud = My_crud(Region)


class Forecast_service:
    async def __raise_condition(self, condition: str):
        if not await weather_condition_crud.exist(
            filters=[Weather_condition.condition == condition],
        ):
            raise HTTPException(status_code=400, detail="bad condition")

    async def __region_not_found(self, regionId):
        if not await region_crud.exist([Region.id == regionId]):
            raise HTTPException(status_code=404, detail="bad regionId")

    async def __forecast_not_found(self, weatherForecast):
        if not await forecast_crud.exist([Forecast.id == weatherForecast]):
            raise HTTPException(
                status_code=404,
                detail="bad weatherForecast"
            )

#     # useful funcs end

    async def create_forecast(
        self,
        payload: Upload_forecast,
        user_id: int
    ):
        await raise_401_error(user_id)
        await self.__raise_condition(payload.weatherCondition)
        await self.__region_not_found(payload.regionId)

        new_payload = Forecast_to_sql(**payload.model_dump())
        new_payload.dateTime = (
            datetime.fromisoformat(payload.dateTime).replace(tzinfo=None)
        )

        return await forecast_crud.create(
            record=new_payload,
            Output_model=Forecast_response
        )

    async def get_forecast(self, weatherForecast: int, user_id: int):
        await raise_401_error(user_id)
        await self.__forecast_not_found(weatherForecast)

        return await forecast_crud.get(
            filters=[Forecast.id == weatherForecast],
            Output_model=Forecast_response
        )

    async def edit_forecast(
        self,
        weatherForecast: int,
        payload: Update_forecast,
        user_id: int
    ):
        await raise_401_error(user_id)
        await self.__raise_condition(payload.weatherCondition)
        await self.__forecast_not_found(weatherForecast)

        new_payload = Forecast_to_sql(**payload.model_dump())
        new_payload.dateTime = (
            datetime.fromisoformat(payload.dateTime).replace(tzinfo=None)
        )

        return await forecast_crud.patch(
            filters=[Forecast.id == weatherForecast],
            new_data=new_payload.model_dump(exclude_none=True),
            Output_model=Forecast_response
        )

    async def delete_forecast(self, weatherForecast: int, user_id: int):
        await raise_401_error(user_id)
        await self.__forecast_not_found(weatherForecast)

        return await forecast_crud.remove([Forecast.id == weatherForecast])
